package com.tmt.im.manager.interfaces.impl;

import com.alibaba.fastjson2.JSONObject;
import com.tmt.im.common.yunxin.ErrorCode;
import com.tmt.im.common.yunxin.YunXinHelper;
import com.tmt.im.jpa.entity.IMUser;
import com.tmt.im.manager.common.Constant;
import com.tmt.im.manager.config.beans.CurrentServiceProperties;
import com.tmt.im.manager.config.beans.YunXinProperties;
import com.tmt.im.manager.interfaces.IYunXinInterface;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.UUID;

/**
 * @Description TODO
 * @Author wuyi
 * @Date 2024/9/13 8:52
 * @Version 1.0
 **/
@Slf4j
@Order(0)
public class YunXinManager_V9 implements IYunXinInterface, ApplicationContextAware {

    private static final String SUPPORTED_API_VERSION = "v9";

    private static final String REG_ACCOUNT_URL = "https://api.netease.im/nimserver/user/create.action";

    private static final String UPDATE_ACCOUNT_URL = "https://api.netease.im/nimserver/user/updateUinfo.action";

    private static final String REFRESH_TOKEN_URL = "https://api.netease.im/nimserver/user/update.action";

    private static final String APPLY_FRIEND_URL = "https://api.netease.im/nimserver/friend/add.action";

    private static final String UPDATE_FRIEND_ALIAS_URL = "https://api.netease.im/nimserver/friend/update.action";

    private static final String DELETE_FRIEND_URL = "https://api.netease.im/nimserver/friend/delete.action";


    private static final String QUERY_UPDATED_FRIENDS_URL = "https://api.netease.im/nimserver/friend/get.action";


    private static final String SEND_CHAT_MESSAGE_URL = "https://api.netease.im/nimserver/msg/sendMsg.action";

    private static final String PULL_IN_BLACK_BILL_URL = "https://api.netease.im/nimserver/user/setSpecialRelation.action";


    private static final String UPDATE_SESSION_INFO_URL = "https://api.netease.im/nimserver/team/update.action";

    private YunXinProperties yunXinProperties;

    private CurrentServiceProperties currentServiceProperties;

    @Override
    public boolean supported(IYunXinInterface iYunXinInterface, Method method, Object[] params) {
        return SUPPORTED_API_VERSION.equalsIgnoreCase(Constant.YUN_XIN_API_VERSION);
    }

    @Override
    public boolean registerUser(IMUser imUser, StringBuilder error) {
        try {
            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
            reqParam.add("accid", "" + imUser.getId());
            reqParam.add("name", imUser.getNickname());
            reqParam.add("icon", "http://" + currentServiceProperties.getExternalClientService() + imUser.getAvatar());
            reqParam.add("mobile", imUser.getMobile());
            reqParam.add("gender", imUser.getSex() != null ? imUser.getSex().getType() : 0);

            JSONObject jsonObject = YunXinHelper.exchange(REG_ACCOUNT_URL, HttpMethod.POST, reqParam, yunXinProperties);
            Long code = jsonObject.getLong("code");
            if (code == 200L) {
                imUser.setImToken(jsonObject.getJSONObject("info").getString("token"));
                return true;
            } else if (code == 414L && "already register".equals(jsonObject.get("desc"))) {
                return refreshUserToken(imUser, error);
            }
            throwExceptionByCode(code, jsonObject);
        } catch (Exception ex) {
            error.append(ex.getMessage());
        }
        return false;
    }

    @Override
    public boolean updateUserInfo(IMUser imUser, StringBuilder error) {
        try {
            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
            reqParam.add("accid", "" + imUser.getId());
            reqParam.add("name", imUser.getNickname());
            reqParam.add("mobile", imUser.getMobile());
            reqParam.add("icon", "http://" + currentServiceProperties.getExternalClientService() + imUser.getAvatar());
            reqParam.add("gender", imUser.getSex() != null ? imUser.getSex().getType() : 0);

            JSONObject jsonObject = YunXinHelper.exchange(UPDATE_ACCOUNT_URL, HttpMethod.POST, reqParam, yunXinProperties);
            Long code = jsonObject.getLong("code");
            if (code == 200L) {
                return true;
            }
            throwExceptionByCode(code, jsonObject);
        } catch (Exception ex) {
            error.append(ex.getMessage());
        }
        return false;
    }

    @Override
    public boolean updateUserAvatar(Long userId, String avatar, StringBuilder error) {
        try {
            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
            reqParam.add("accid", "" + userId);
            reqParam.add("icon", avatar);
            JSONObject jsonObject = YunXinHelper.exchange(UPDATE_ACCOUNT_URL, HttpMethod.POST, reqParam, yunXinProperties);
            Long code = jsonObject.getLong("code");
            if (code == 200L) {
                return true;
            }
            throwExceptionByCode(code, jsonObject);
        } catch (Exception ex) {
            error.append(ex.getMessage());
        }
        return false;
    }

    @Override
    public boolean updateSessionAvatar(Long tid, Long ownerId, String avatar, StringBuilder error) {
        try {
            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
            reqParam.add("tid", tid);
            reqParam.add("owner", "" + ownerId);
            reqParam.add("icon", avatar);

            JSONObject jsonObject = YunXinHelper.exchange(UPDATE_SESSION_INFO_URL, HttpMethod.POST, reqParam, yunXinProperties);
            Long code = jsonObject.getLong("code");
            if (code == 200L) {
                return true;
            }
            throwExceptionByCode(code, jsonObject);
        } catch (Exception ex) {
            error.append(ex.getMessage());
        }
        return false;
    }

    @Override
    public boolean refreshUserToken(IMUser imUser, StringBuilder error) {
        try {
            String token = UUID.randomUUID().toString().replace("-", "");

            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
            reqParam.add("accid", "" + imUser.getId());
            reqParam.add("token", token);

            JSONObject jsonObject = YunXinHelper.exchange(REFRESH_TOKEN_URL, HttpMethod.POST, reqParam, yunXinProperties);
            Long code = jsonObject.getLong("code");
            if (code == 200L) {
                imUser.setImToken(token);
                return true;
            }
            throwExceptionByCode(code, jsonObject);
        } catch (Exception ex) {
            error.append(ex.getMessage());
        }
        return false;
    }

    @Override
    public boolean applyFriend(Long creatorId, Long targetId, int type, String targetAlias, String note, StringBuilder error) {
        try {
            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
            reqParam.add("accid", "" + creatorId);
            reqParam.add("faccid", "" + targetId);
            reqParam.add("type", type);
            if (StringUtils.hasText(note)) {
                reqParam.add("msg", note);
            }
            JSONObject jsonObject = YunXinHelper.exchange(APPLY_FRIEND_URL, HttpMethod.POST, reqParam, yunXinProperties);
            Long code = jsonObject.getLong("code");
            if (code == 200L) {
                return true;
            }
            throwExceptionByCode(code, jsonObject);
        } catch (Exception ex) {
            error.append(ex.getMessage());
        }
        return false;
    }

    @Override
    public boolean updateFriend(Long creatorId, Long targetId, String targetAlias, StringBuilder error) {
        try {
            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
            reqParam.add("accid", "" + creatorId);
            reqParam.add("faccid", "" + targetId);
            reqParam.add("alias", targetAlias);
            JSONObject jsonObject = YunXinHelper.exchange(UPDATE_FRIEND_ALIAS_URL, HttpMethod.POST, reqParam, yunXinProperties);
            Long code = jsonObject.getLong("code");
            if (code == 200L) {
                return true;
            }
            throwExceptionByCode(code, jsonObject);
        } catch (Exception ex) {
            error.append(ex.getMessage());
        }
        return false;
    }

    @Override
    public boolean deleteFriend(Long currentUserId, Long friendId, StringBuilder error) {
        try {
            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
            reqParam.add("accid", "" + currentUserId);
            reqParam.add("faccid", "" + friendId);
            reqParam.add("isDeleteAlias", true);
            JSONObject jsonObject = YunXinHelper.exchange(DELETE_FRIEND_URL, HttpMethod.POST, reqParam, yunXinProperties);
            Long code = jsonObject.getLong("code");
            if (code == 200L) {
                return true;
            }
            throwExceptionByCode(code, jsonObject);
        } catch (Exception ex) {
            error.append(ex.getMessage());
        }
        return false;
    }

    /**
     * 将指定的好友拉入或拉出黑名单
     *
     * @param currentUserId
     * @param friendId
     * @param pullIn
     * @param error
     * @return
     */
    public boolean pullInBlackBill(Long currentUserId, Long friendId, boolean pullIn, StringBuilder error) {
        try {
            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
            reqParam.add("accid", "" + currentUserId);
            reqParam.add("targetAcc", "" + friendId);
            reqParam.add("relationType", 1);
            reqParam.add("value", pullIn ? 1 : 0);
            JSONObject jsonObject = YunXinHelper.exchange(PULL_IN_BLACK_BILL_URL, HttpMethod.POST, reqParam, yunXinProperties);
            Long code = jsonObject.getLong("code");
            if (code == 200L) {
                return true;
            }
            throwExceptionByCode(code, jsonObject);
        } catch (Exception ex) {
            error.append(ex.getMessage());
        }
        return false;
    }

    /**
     * 设置或解除好友的免打扰状态。
     *
     * @param currentUserId
     * @param friendId
     * @param noDisturbing
     * @param error
     * @return
     */
    public boolean enableNoDisturbing(Long currentUserId, Long friendId, boolean noDisturbing, StringBuilder error) {
        try {
            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
            reqParam.add("accid", "" + currentUserId);
            reqParam.add("targetAcc", "" + friendId);
            reqParam.add("relationType", 2);
            reqParam.add("value", noDisturbing ? 1 : 0);
            JSONObject jsonObject = YunXinHelper.exchange(PULL_IN_BLACK_BILL_URL, HttpMethod.POST, reqParam, yunXinProperties);
            Long code = jsonObject.getLong("code");
            if (code == 200L) {
                return true;
            }
            throwExceptionByCode(code, jsonObject);
        } catch (Exception ex) {
            error.append(ex.getMessage());
        }
        return false;
    }

//    @Override
//    public boolean queryUpdatedFriends(Long currentUserId, Long startTime, List<UpdatedFriendInfo> friendInfos, StringBuilder error){
//        try {
//            MultiValueMap<String, Object> reqParam = new LinkedMultiValueMap<>();
//            reqParam.add("accid", "" + currentUserId);
//            reqParam.add("updatetime", startTime);
//            JSONObject jsonObject = YunXinHelper.exchange(QUERY_UPDATED_FRIENDS_URL, HttpMethod.POST, reqParam, yunXinProperties);
//            Long code = jsonObject.getLong("code");
//            if (code == 200L) {
//                JSONArray array = JSONArray.parseArray(jsonObject.getString("friends"));
//                for (Object obj : array) {
//                    JSONObject json = (JSONObject) obj;
//                    UpdatedFriendInfo info = new UpdatedFriendInfo();
//                    friendInfos.add(info);
//                    info.setId(Long.parseLong(json.getString("faccid")));
//                    info.setBidirection(json.getBoolean("bidirection"));
//                    info.setUpdateTime(new Timestamp(json.getLong("createtime")));
//                }
//                return true;
//            }
//            throwExceptionByCode(code, jsonObject);
//        } catch (Exception ex) {
//            error.append(ex.getMessage());
//        }
//        return false;
//    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        yunXinProperties = applicationContext.getBean(YunXinProperties.class);
        currentServiceProperties = applicationContext.getBean(CurrentServiceProperties.class);
    }

    private void throwExceptionByCode(Long code, JSONObject jsonObject) throws Exception {
        String errorInfo = ErrorCode.getErrorMessage(Constant.YUN_XIN_API_VERSION, code);
        if (StringUtils.hasText(errorInfo)) {
            if (code == 414L) {
                errorInfo = MessageFormat.format(errorInfo, jsonObject.get("desc"));
            }
            throw new Exception(errorInfo);
        } else {
            throw new Exception(MessageFormat.format("云信业务错误:{0}", jsonObject.toJSONString()));
        }
    }
}
